package com.aipanda.util;

import com.aipanda.pojo.CommonAttributes;
import freemarker.core.Environment;
import freemarker.template.Configuration;
import freemarker.template.ObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.utility.DeepUnwrap;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.commons.beanutils.converters.DateConverter;
import org.springframework.context.ApplicationContext;
import org.springframework.util.Assert;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;


public final class FKUtils {
	private static final ConvertUtilsBean convertUtilsBean = new FKConvertUtils();

	static {
		DateConverter localDateConverter = new DateConverter();
		localDateConverter.setPatterns(CommonAttributes.DATE_PATTERNS);
		convertUtilsBean.register(localDateConverter, Date.class);
	}

	public static String process(String template, Map<String, ?> model) {
		Configuration configuration = null;
		ApplicationContext applicationContext = SpringUtils.getApplicationContext();
		if (applicationContext != null) {
			FreeMarkerConfigurer freeMarkerConfigurer = SpringUtils.getBean("freeMarkerConfigurer", FreeMarkerConfigurer.class);
			if (freeMarkerConfigurer != null){
				configuration = freeMarkerConfigurer.getConfiguration();
			}
		}
		return process(template, model, configuration);
	}

	public static String process(String template, Map<String, ?> model,Configuration configuration) {
		if (template == null){
			return null;
		}
		if (configuration == null){
			configuration = new Configuration();
		}
		StringWriter stringWriter = new StringWriter();
		try {
			new Template("template", new StringReader(template), configuration).process(model, stringWriter);
		} catch (TemplateException templateException) {
			templateException.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return stringWriter.toString();
	}

	@SuppressWarnings("unchecked")
	public static <T> T getParameter(String name, Class<T> type,Map<String, TemplateModel> params) {
		Assert.hasText(name);
		Assert.notNull(type);
		Assert.notNull(params);
		TemplateModel templateModel = params.get(name);
		if (templateModel == null){
			return null;
		}
		Object value = null;
		try {
			value = DeepUnwrap.unwrap(templateModel);
		} catch (TemplateModelException e) {
			e.printStackTrace();
		}
		return (T) convertUtilsBean.convert(value, type);
	}

	public static TemplateModel getVariable(String name, Environment env) {
		Assert.hasText(name);
		Assert.notNull(env);
		try {
			return env.getVariable(name);
		} catch (TemplateModelException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void setVariable(String name, Object value, Environment env) {
		Assert.hasText(name);
		Assert.notNull(env);
		if ((value instanceof TemplateModel))
			env.setVariable(name, (TemplateModel) value);
		else
			try {
				env.setVariable(name, ObjectWrapper.BEANS_WRAPPER.wrap(value));
			} catch (TemplateModelException e) {
				e.printStackTrace();
			}
	}

	public static void setVariables(Map<String, Object> variables,Environment env) {
		Assert.notNull(variables);
		Assert.notNull(env);
		Iterator<Map.Entry<String, Object>> iterator = variables.entrySet().iterator();
		while (iterator.hasNext()) {
			Map.Entry<String, Object> entry = iterator.next();
			String key = entry.getKey();
			Object value = entry.getValue();
			if (value instanceof TemplateModel){
				env.setVariable(key, (TemplateModel) value);
			}else
				try {
					env.setVariable(key, ObjectWrapper.BEANS_WRAPPER.wrap(value));
				} catch (TemplateModelException e) {
					e.printStackTrace();
				}
		}
	}
}